//
//  GameControl.m
//  firstllk
//
//  Created by Huang Michael on 10-01-05.
//  Copyright 2010 __MyCompanyName__. All rights reserved.
//

#include <time.h>

#import "GameControl.h"
#import "mainpage.h"
#import "PausePage.h"
#import "Record.h"
#import "HighScoresLayer.h"

@implementation SpriteStatus

- (id) init
{
	self = [super init];
	stype = 0;
	isLife = YES;
	sp = nil;
	
	return self;
}

@end


@implementation GameControl

- (id) init
{
	self = [super init];
	if (!self) {
		return nil;
	}
	
	gSelf = self;

	nLevel = 1;

	isSelect = NO;
	isLined = NO;
	isGameOver = NO;
	isGameSuccessed = NO;
	isAutoCheck = NO;
	nScore = 0;
	
	nLifeCounts = LIFE_COUNT;
	nHints = HINT_COUNT;
	gameTime = GAMETIME;
	levelTime = gameTime;
	nSpCounts = MAX_SPRITES;
	nScorePerPair = SCORE_PER_PAIR;

	nCrtTypeOfSp = START_TYPE_OF_SPRITE;

	
	CCBitmapFontAtlas *lbScoreTitle = [CCBitmapFontAtlas bitmapFontAtlasWithString:@"SCORE" fntFile:@"font01.fnt"];
	lbScoreTitle.anchorPoint = ccp(0, 0);
	lbScoreTitle.scale = 0.7;
	[self addChild:lbScoreTitle z:1 tag:TAG_LBSCORE];
	lbScoreTitle.position = ccp(12, 35);
	
	CCBitmapFontAtlas *lbScore = [CCBitmapFontAtlas bitmapFontAtlasWithString:@"000000" fntFile:@"font01.fnt"];
	lbScore.anchorPoint = ccp(0, 0);
	lbScore.scale = 0.7;
	[self addChild:lbScore z:1 tag:TAG_SCORE];
	lbScore.position = ccp(12, 18);

	CCSprite * sp_bg = [CCSprite spriteWithFile:@"p2.png"];

	sp_bg.anchorPoint = CGPointZero;
	
	[self addChild:sp_bg z:-1 tag:TAG_BACKGROUND];
	

	prog = [CCProgressTimer progressWithFile:@"time01.png"];
	prog.position = ccp(170,81);
	prog.type = kCCProgressTimerTypeHorizontalBarLR;
	
	[self addChild:prog z:8 tag:TAG_TIMERPRORESS];
	
	[prog runAction:[CCProgressFromTo actionWithDuration:(ccTime)levelTime from:100 to:0]];
	
	CCSprite * spPauseNormal = [CCSprite spriteWithFile:@"btn_pause.png"];
	CCSprite * spPauseDis = [CCSprite spriteWithFile:@"btn_pause_dis.png"];
	mniPause = [CCMenuItemSprite itemFromNormalSprite:spPauseNormal selectedSprite:spPauseDis target:self selector:@selector(pauseGame:)];
	
	CCMenu *mn1 = [CCMenu menuWithItems:mniPause, nil];
	//设置菜单项对齐模式
	[mn1 alignItemsVertically];
	
	//设置菜单颜色，位置，缩放比例
	mn1.position = ccp( 100, 46 );
	
	[self addChild:mn1 z:1 tag:TAG_PAUSE];

	CCSprite * spRefreshNormal = [CCSprite spriteWithFile:@"btn_reload.png"];
	CCSprite * spRefreshDis = [CCSprite spriteWithFile:@"btn_reload_dis.png"];
	mniRefresh = [CCMenuItemSprite itemFromNormalSprite:spRefreshNormal 
												selectedSprite:spRefreshDis 
												disabledSprite:spRefreshDis
													target:self
													  selector:@selector(refreshSpriteMap:)];
	
	CCMenu *mn2 = [CCMenu menuWithItems:mniRefresh, nil];
	//设置菜单项对齐模式
	[mn2 alignItemsVertically];

	//设置菜单颜色，位置，缩放比例
	mn2.position = ccp( 154, 46 );
	
	[self addChild:mn2 z:1 tag:TAG_REFRESH];
	
	NSString *str = [NSString stringWithFormat:@"%d", (int)nLifeCounts];
	CCLabel *lbLifeCnt = [CCLabel labelWithString:str fontName:@"Marker Felt" fontSize:24];
	lbLifeCnt.position = ccp(174,65);
	lbLifeCnt.color = ccc3(250,50,50);
	lbLifeCnt.scale = 0.8;
	
	[self addChild:lbLifeCnt z:2 tag:TAG_REFRESH_CNT];
	
	
	NSString *strLevel = [NSString stringWithFormat:@"Level %d", (int)nLevel];
	CCLabel *lbLevle = [CCLabel labelWithString:strLevel fontName:@"Marker Felt" fontSize:24];
	lbLevle.position = ccp(60,465);
	lbLevle.color = ccc3(50, 250, 50);
	lbLevle.scale = 0.8;
	[self addChild:lbLevle z:2 tag:TAG_LBLEVEL];
	
	CCSprite * spHintNormal = [CCSprite spriteWithFile:@"btn_hint.png"];
	CCSprite * spHintDis = [CCSprite spriteWithFile:@"btn_hint_dis.png"];
	mniHint = [CCMenuItemSprite itemFromNormalSprite:spHintNormal
												selectedSprite:spHintDis
												disabledSprite:spHintDis
														target:self
													  selector:@selector(checkAndDisplayHint:)];
	
	CCMenu *mn3 = [CCMenu menuWithItems:mniHint, nil];
	//设置菜单项对齐模式
	[mn3 alignItemsVertically];
	
	//设置菜单颜色，位置，缩放比例
	mn3.position = ccp( 210, 46 );
	
	[self addChild:mn3 z:1 tag:TAG_HINT];
	
	NSString *str2 = [NSString stringWithFormat:@"%d", (int)nHints];
	CCLabel *lbHintCnt = [CCLabel labelWithString:str2 fontName:@"Marker Felt" fontSize:24];
	lbHintCnt.position = ccp(230,65);
	lbHintCnt.color = ccc3(250,50,50);
	lbHintCnt.scale = 0.8;
	
	[self addChild:lbHintCnt z:2 tag:TAG_HINT_CNT];
	
	
	for (int i=0; i<nCrtTypeOfSp; i++) {
		cntArray[i]=4;
	}
	
	[self initSpriteMap];
	
	// accept touch now!
	self.isTouchEnabled = YES;		
	
	
	[self schedule:@selector(secondTimer:) interval:1];
	
	//添加音乐开关
	CCSprite *spSoundOn = [CCSprite spriteWithFile:@"soundOn.png"];
	CCSprite *spSoundOff = [CCSprite spriteWithFile:@"soundOff.png"];
	//	CCMenuItem *miSound = [CCMenuItemSprite itemFromNormalSprite:spSoundOn selectedSprite:spSoundOn target:self selector:@selector(SetSound:)];
	CCMenuItemToggle *mitSound = [CCMenuItemToggle itemWithTarget:self selector:@selector(OnSetSound:) items:
								  [CCMenuItemSprite itemFromNormalSprite:spSoundOn selectedSprite:spSoundOn],
								  [CCMenuItemSprite itemFromNormalSprite:spSoundOff selectedSprite:spSoundOff],
								  nil];
	
#ifdef EN_SOUND
	mitSound.selectedIndex = [SimpleAudioEngine sharedEngine].muted;// == YES?0:1);	//使用当前音效状态选中音效开关
#endif
	CCMenu *mSound = [CCMenu menuWithItems:mitSound, nil];
	// ask director the the window size
	CGSize size = [[CCDirector sharedDirector] winSize];
	mSound.position = ccp(size.width-20, size.height-20);
	[self addChild:mSound z:2 tag:TAG_SOUND];
	
	
#ifdef EN_SOUND	
//	[[CDAudioManager sharedManager] playBackgroundMusic:@"gameBgMusic.mp3" loop:YES];
	[[SimpleAudioEngine sharedEngine] preloadBackgroundMusic:@"gameBgMusic.mp3"];
	if ([SimpleAudioEngine sharedEngine].muted) {
		[SimpleAudioEngine sharedEngine].muted = NO;
		[[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"gameBgMusic.mp3" loop:YES];
		[SimpleAudioEngine sharedEngine].muted = YES;
	}
	else {
		[[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"gameBgMusic.mp3" loop:YES];
	}

	[[SimpleAudioEngine sharedEngine] preloadEffect:@"glass.wav"];
	[[SimpleAudioEngine sharedEngine] preloadEffect:@"wrongMusic.mp3"];
#endif	
	return self;
	
}

- (void) initSpriteMap
{	
	//初始化精灵图
	CCSprite *sprite;
	SpriteStatus * sps;

	mgr = [CCSpriteSheet spriteSheetWithFile:@"40pixIcon.png" capacity:MAX_SPRITES];
	[self addChild:mgr z:2 tag:TAG_SPMGR];
	
	
	

	memset(pSpListHead, 0, MAXTYPE_OF_SPRITE * sizeof(ST_SPLIST));
	
	time_t t = time(nil);
	srand(t);
	
	for (int i=0; i<MAX_SPRITE_COL+2; i++) {
		for (int j=0; j<MAX_SPRITE_ROW+2; j++) {
			if ((i == 0) || (i == MAX_SPRITE_COL+1)) {
				sps = [[SpriteStatus alloc] init];
				sps->stype = -1;
				sps->sp = nil;
				sps->isLife = NO;
			}
			else if ((j == 0) || (j == MAX_SPRITE_ROW+1)){
				sps = [[SpriteStatus alloc] init];
				sps->stype = -1;
				sps->sp = nil;
				sps->isLife = NO;
			}
			else{
				do {
					int r = rand() % nCrtTypeOfSp;
					int n = cntArray[r];
					int rndCnt = nLevel;
					BOOL neighbour = NO;
					if (rand() % (nLevel / 2)) {
						while(1)//设定一个概率，随着level提高
						{//进行相邻检测
							r = (r + rand()) % nCrtTypeOfSp;
							n = cntArray[r];
							if (n <= 0) {
								continue;
							}
							neighbour = NO;
							ST_SPLIST *pTemp = pSpListHead[r].spNext;
							ST_SPLIST *pPrev = &(pSpListHead[r]);
							while (pTemp && pTemp->spNode) {
								if ((pTemp->spNode->pos.x == i) || (pTemp->spNode->pos.y == j)) {
									neighbour = YES;
									break;
								}
								pPrev = pTemp;
								pTemp = pTemp->spNext;
							}
							if ((neighbour == NO) ||(rndCnt-- < 0)) {
								break;
							}
						}
						
					}
					if (n>0) {
						int x= r % 5;
						sprite = [CCSprite spriteWithTexture:mgr.texture rect:CGRectMake(SPRITE_WIDTH*x,SPRITE_HEIGHT*(r/5),SPRITE_WIDTH,SPRITE_HEIGHT) ];
						sprite.anchorPoint = ccp(0.5f, 0.5f);
						//sprite.anchorPoint = ccp(15, 15);
						sprite.position = ccp(MAP_LEFT+SPRITE_WIDTH*(i-1)+(SPRITE_WIDTH/2), MAP_UP-SPRITE_HEIGHT-SPRITE_HEIGHT*(j-1)+SPRITE_HEIGHT/2);
						[mgr addChild:sprite z:1 tag:TAG_SPMGR+i+j*MAX_SPRITE_COL];
						
						sps = [[SpriteStatus alloc] init];
						sps->stype = r;
						sps->isLife = YES;
						sps->sp = sprite;
						sps->pos.x = i;
						sps->pos.y = j;
						cntArray[r]--;
						
						ST_SPLIST * p = malloc(sizeof(ST_SPLIST));
						if (p == nil) {
							//内存不足，额外处理
							return;
						}
						ST_SPLIST *pTemp = pSpListHead[r].spNext;
						ST_SPLIST *pPrev = &(pSpListHead[r]);
						while (pTemp && pTemp->spNode) {
							pPrev = pTemp;
							pTemp = pTemp->spNext;
						}
							pPrev->spNext = p;
							p->spPrev = pPrev;
							p->spNext = nil;
							p->spNode = sps;
						
						break;
					}
				} while (1);	
			}
			mapArray[i][j] = sps;
		}
	}
}


- (void) secondTimer : (ccTime) dt
{
	gameTime --;
	
	if (gameTime < 0) {
		//game over
		isGameOver = YES;
		
		self.isTouchEnabled = NO;		
		
		[self unschedule:@selector(secondTimer:)];
		[mniRefresh setIsEnabled:NO];
		[mniHint setIsEnabled:NO];
		[mniPause setIsEnabled:NO];
		
#ifdef EN_SOUND	
		[[SimpleAudioEngine sharedEngine] stopBackgroundMusic];
#endif
		
		NSArray *scores = [Record getHighScores];
		int scoreIndex = 0;
		for (int i=0; i<[scores count]; scoreIndex++, i++) {
			Record *each = [scores objectAtIndex:i];
			if (each.score<= nScore) {
				scoreIndex = i;
				break;
			}		
		}
		if ((scoreIndex >= 0) && (scoreIndex < kMaxRecordCount)) {
			[self getPlayerName];
			
		}
		else {
			[self timeout];
		}

		
		
	}

}


-(void) timeout 
{
	
	
	CCLabel *label = [CCLabel labelWithString:@"Time Up!" fontName:@"Marker Felt" fontSize:64];
	label.position = ccp(160,320);
	label.color = ccc3(250,50,50);
	
	
	CCMenuItem * mni1 = [CCMenuItemFont itemFromString:@"back" target:self selector:@selector(returnMain:)];
	CCMenu *mn = [CCMenu menuWithItems:mni1, nil];
	mn.color = ccc3(80,50,250);
	mn.position = ccp( 160 , 180 );
	
	
	NSString *str = [NSString stringWithFormat:@"Finale Score:%06d", (int)nScore];
	CCLabel *lbScore = [CCLabel labelWithString:str fontName:@"Marker Felt" fontSize:32];
	lbScore.position = ccp(160,260);
	lbScore.color = ccc3(250,50,50);
	
	[self addChild:label z:100 tag:TAG_LBFINAL];
	[self addChild:lbScore z:100 tag:TAG_LBFINALSCORE];
	[self addChild:mn z:101 tag:TAG_MNBACK];
}	
- (void)getPlayerName{
	
	changePlayerAlert = [UIAlertView new];
	changePlayerAlert.title = @"High Score!";
	changePlayerAlert.message = @"\n";
	changePlayerAlert.delegate = self;
	[changePlayerAlert addButtonWithTitle:@"Save"];
//	[changePlayerAlert addButtonWithTitle:@"Cancel"];
	[changePlayerAlert show];
	
	CGRect frame = changePlayerAlert.frame;
	frame.origin.y -= 100.0f;
	changePlayerAlert.frame = frame;
	
	changePlayerTextField = [[UITextField alloc] initWithFrame:CGRectMake(20, 45, 245, 27)];
	changePlayerTextField.borderStyle = UITextBorderStyleRoundedRect;
	[changePlayerAlert addSubview:changePlayerTextField];
	//	changePlayerTextField.placeholder = @"Enter your name";
	//	changePlayerTextField.clearButtonMode = UITextFieldViewModeWhileEditing;
	changePlayerTextField.keyboardType = UIKeyboardTypeDefault;
	changePlayerTextField.returnKeyType = UIReturnKeyDone;
	changePlayerTextField.autocorrectionType = UITextAutocorrectionTypeNo;
	changePlayerTextField.autocapitalizationType = UITextAutocapitalizationTypeNone;
	changePlayerTextField.delegate = nil;
	[changePlayerTextField becomeFirstResponder];
}
- (void)saveHighScore {

	NSString * playerName = [changePlayerTextField.text retain];

	[User saveName:playerName];
	[User saveScore:nScore];
	[User saveWinedLevel:nLevel];
	[Record trySaveScoreRecord:[Record createCurrentRecord]];
	
	
	[Record getHighScores];
	
	CCScene *sc = [CCScene node];
	[sc addChild:[HighScoresLayer node]];
	[[CCDirector sharedDirector] replaceScene: [CCZoomFlipXTransition transitionWithDuration:0.5f scene:sc]];
	

}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
	//	NSLog(@"alertView:clickedButtonAtIndex: %i",buttonIndex);
	
	if(buttonIndex == 0) {
		[self saveHighScore];
	} else {
		// nothing
	}
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
	//	NSLog(@"textFieldShouldReturn");
	[changePlayerAlert dismissWithClickedButtonIndex:0 animated:YES];
	[self saveHighScore];
	return YES;
}


-(void) gameover 
{
	CCLabel *label = [CCLabel labelWithString:@"Game Over!" fontName:@"Marker Felt" fontSize:64];
	label.position = ccp(160,320);
	label.color = ccc3(250,50,50);
	
	
	CCMenuItem * mni1 = [CCMenuItemFont itemFromString:@"back" target:self selector:@selector(returnMain:)];
	CCMenu *mn = [CCMenu menuWithItems:mni1, nil];
	mn.color = ccc3(80,200,250);
	mn.position = ccp( 160 , 180 );
	
	
	NSString *str = [NSString stringWithFormat:@"Finale Score:%06d", (int)nScore];
	CCLabel *lbScore = [CCLabel labelWithString:str fontName:@"Marker Felt" fontSize:32];
	lbScore.position = ccp(160,260);
	lbScore.color = ccc3(250,50,50);
	
	[self addChild:label z:100 tag:TAG_LBFINAL];
	[self addChild:lbScore z:100 tag:TAG_LBFINALSCORE];
	[self addChild:mn z:101 tag:TAG_MNBACK];
	
	
	
}

- (void) refreshSpriteMap:(id)sender
{
	//初始化精灵图
	CCSprite *sprite;
	SpriteStatus * sps;
	
	nLifeCounts--;

	if (nLifeCounts == 0)
		[mniRefresh setIsEnabled:NO];
	
	NSString *string = [NSString stringWithFormat:@"%d", (int)nLifeCounts];
	
	CCLabel *label1 = (CCLabel*)[self getChildByTag:TAG_REFRESH_CNT];
	[label1 setString:string];
	

	if (nLifeCounts < 0) {
		//游戏结束
		
		//game over
		isGameOver = YES;
		
		self.isTouchEnabled = NO;		
		
		[self unschedule:@selector(secondTimer:)];
		[mniRefresh setIsEnabled:NO];
		[mniHint setIsEnabled:NO];
		[mniPause setIsEnabled:NO];
		
#ifdef EN_SOUND	
		[[SimpleAudioEngine sharedEngine] stopBackgroundMusic];
#endif
		
		NSArray *scores = [Record getHighScores];
		int scoreIndex = 0;
		for (int i=0; i<[scores count]; scoreIndex++, i++) {
			Record *each = [scores objectAtIndex:i];
			if (each.score<= nScore) {
				scoreIndex = i;
				break;
			}		
		}
		if ((scoreIndex >= 0) && (scoreIndex < kMaxRecordCount)) {
			[self getPlayerName];
			
		}
		else {
			[self gameover];
		}
		
	}
//计算剩余的各种类型数量	
	
	for (int i=0; i<nCrtTypeOfSp; i++) {
		ST_SPLIST *pTemp = pSpListHead[i].spNext;
		cntArray[i]=0;
		while (pTemp) {
			if(pTemp->spNode->isLife == YES)
				cntArray[i]++;
			pTemp = pTemp->spNext;
		}
	}
	
//记录存活精灵位置，释放整个精灵表
	BOOL mapLife[MAX_SPRITE_COL+2][MAX_SPRITE_ROW+2];
	for (int i=0; i<MAX_SPRITE_COL+2; i++) {
		for (int j=0; j<MAX_SPRITE_ROW+2; j++) {
			mapLife[i][j] = mapArray[i][j]->isLife;
			if (mapArray[i][j]->sp != nil) {
				[mgr removeChild:mapArray[i][j]->sp cleanup:YES];
				[mapArray[i][j] release];
			}
		}
	}
	[gSelf removeChild:mgr cleanup:YES];
	
//根据剩余精灵数量和位图，重新生成精灵表
	mgr = [CCSpriteSheet spriteSheetWithFile:@"40pixIcon.png" capacity:MAX_SPRITES];
	[self addChild:mgr z:2 tag:TAG_SPMGR];

	
	memset(pSpListHead, 0, MAXTYPE_OF_SPRITE * sizeof(ST_SPLIST));

	time_t t = time(nil);
	srand(t);
	
	for (int i=0; i<MAX_SPRITE_COL+2; i++) {
		for (int j=0; j<MAX_SPRITE_ROW+2; j++) {
			if ((i == 0) || (i == MAX_SPRITE_COL+1)) {
				sps = [[SpriteStatus alloc] init];
				sps->stype = -1;
				sps->sp = nil;
				sps->isLife = NO;
			}
			else if ((j == 0) || (j == MAX_SPRITE_ROW+1)){
				sps = [[SpriteStatus alloc] init];
				sps->stype = -1;
				sps->sp = nil;
				sps->isLife = NO;
			}
			else {
				sps = [[SpriteStatus alloc] init];
				sps->stype = -1;
				sps->sp = nil;
				sps->isLife = NO;
				if (mapLife[i][j]) {
					do {
						int r = rand() % nCrtTypeOfSp;
						int n = cntArray[r];
						int rndCnt = nLevel-1;//重排的难度稍稍低一点
						BOOL neighbour = NO;
						if (rand() % (nLevel / 2)) {
							while(1)//设定一个概率，随着level提高
							{//进行相邻检测
								r = (r + rand()) % nCrtTypeOfSp;
								n = cntArray[r];
								if (n <= 0) {
									continue;
								}
								neighbour = NO;
								ST_SPLIST *pTemp = pSpListHead[r].spNext;
								ST_SPLIST *pPrev = &(pSpListHead[r]);
								while (pTemp && pTemp->spNode) {
									if ((pTemp->spNode->pos.x == i) || (pTemp->spNode->pos.y == j)) {
										neighbour = YES;
										break;
									}
									pPrev = pTemp;
									pTemp = pTemp->spNext;
								}
								if ((neighbour == NO) ||(rndCnt-- < 0)) {
									break;
								}
							}
							
						}
						if (n>0) {
							int x= r % 5;
							sprite = [CCSprite spriteWithTexture:mgr.texture rect:CGRectMake(SPRITE_WIDTH*x,SPRITE_HEIGHT*(r/5),SPRITE_WIDTH,SPRITE_HEIGHT) ];
							sprite.anchorPoint = ccp(0.5f, 0.5f);
							//sprite.anchorPoint = ccp(15, 15);
							sprite.position = ccp(MAP_LEFT+SPRITE_WIDTH*(i-1)+(SPRITE_WIDTH/2), MAP_UP-SPRITE_HEIGHT-SPRITE_HEIGHT*(j-1)+SPRITE_HEIGHT/2);
							[mgr addChild:sprite z:1 tag:TAG_SPMGR+i+j*MAX_SPRITE_COL];
							
							sps->stype = r;
							sps->sp = sprite;
							sps->pos.x = i;
							sps->pos.y = j;
							sps->isLife = YES;
							cntArray[r]--;
							
							ST_SPLIST * p = malloc(sizeof(ST_SPLIST));
							if (p == nil) {
								//内存不足，额外处理
								return;
							}
							ST_SPLIST *pTemp = pSpListHead[r].spNext;
							ST_SPLIST *pPrev = &(pSpListHead[r]);
							while (pTemp && pTemp->spNode) {
								pPrev = pTemp;
								pTemp = pTemp->spNext;
							}
							pPrev->spNext = p;
							p->spPrev = pPrev;
							p->spNext = nil;
							p->spNode = sps;
							
							break;
						}
					} while (1);	
				}
			}
			mapArray[i][j] = sps;
		}
	}
	
	
}

- (ST_SPLIST *) getNextValidSpNode: (ST_SPLIST *)node
{
	if (node == nil) {
		return node;
	}
	ST_SPLIST * retNode = node;
	do{
		retNode = retNode->spNext;
		if (retNode == Nil) {
			return retNode;
		}
	}while (retNode->spNode->isLife == NO);
	return retNode;
}

- (void) checkAndDisplayHint:(id)sender
{

	if(!isAutoCheck)
	   nHints--;
	NSString *string = [NSString stringWithFormat:@"%d", (int)nHints];
	
	CCLabel *label1 = (CCLabel*)[self getChildByTag:TAG_HINT_CNT];
	[label1 setString:string];
	
	//从类型链表找到相同的精灵，进行连接检查

	for (int i=0; i<nCrtTypeOfSp; i++) {
		ST_SPLIST *pNode1 = &(pSpListHead[i]);
		
		while (1) {
			pNode1 = [self getNextValidSpNode:pNode1];
			if (pNode1 == Nil) {
				break;//for
			}
			ST_SPLIST *pNode2;
			pNode2 = [self getNextValidSpNode:pNode1];
			if (pNode2 == Nil) {
				break;//for
			}
			while (1) {
				if (YES == [self checkLink:(pNode1->spNode)->pos :(pNode2->spNode)->pos])
				{//成功，提示3秒钟
					//如果是自动检查，则不提示
					if (isAutoCheck) {
						return;
					}
					id act1 = [CCSequence actions:[CCFadeOut actionWithDuration:0.3f],
							   [CCFadeIn actionWithDuration:0.3f],nil];
					id act2 = [CCSequence actions:[CCFadeOut actionWithDuration:0.3f],
							   [CCFadeIn actionWithDuration:0.3f],nil];
					[pNode1->spNode->sp runAction:[CCRepeat actionWithAction:act1 times:3.0f] ];
					[pNode2->spNode->sp runAction:[CCRepeat actionWithAction:act2 times:3.0f] ];
					if (nHints <= 0)
						[mniHint setIsEnabled:NO];
					return;
				}
				else {
					pNode2 = [self getNextValidSpNode:pNode2];
					if (pNode2 == Nil) {
						break;
					}
				}
			}//第二个点的遍历循环
		}//第一个点的遍历循环
	}//每个类型的遍历
	[self refreshSpriteMap:sender];
	return;
}


- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
	
	UITouch *touch = [touches anyObject];
	
	if (isGameSuccessed) {
		
	}
	
	//获取点击坐标
	CGPoint location = [touch locationInView: [touch view]];
	CGPoint convertedLocation = [[CCDirector sharedDirector] convertToGL:location];

	//查找坐标对应的位置
	//方法是坐标xy分别除以每个精灵的宽度，得到一个从屏幕左上角为原点的坐标（xt，yt），表示第几行第几列的精灵。

	//－－－－有一个判断坐标点在RECT内的库函数，有空试一下－－－－！！！！！！！！！！！！

	int xpos,ypos,xt,yt;
	xpos = convertedLocation.x;
	ypos = convertedLocation.y;
	
	xt = (xpos - SPRITE_MAP_LEFT) / SPRITE_WIDTH;
	yt = (SPRITE_MAP_UP - ypos) / SPRITE_HEIGHT;

	if((xt >= 0) && (yt >= 0))//判断xy边界是否有效
	{
		if((xt < MAX_SPRITE_COL) && (yt < MAX_SPRITE_ROW))//判断xy边界是否有效
		{
		
			SpriteStatus * sps;
			sps = mapArray[xt+1][yt+1];
			if(sps->isLife)//判断该点是否有存活精灵h
			{
				if (!isSelect) {//判断是否有已选择精灵，若无，进行选择
					isSelect = YES;
					spsFirst = sps;
//					id act1 = [CCSequence actions:[CCFadeOut actionWithDuration:0.3f],
//							  [CCFadeIn actionWithDuration:0.3f],nil];
					id act = [CCSequence actions:[CCRotateTo actionWithDuration:0.06f angle:10],
							  [CCRotateTo actionWithDuration:0.06f angle:0],
							  [CCRotateTo actionWithDuration:0.06f angle:-10],
							  [CCRotateTo actionWithDuration:0.06f angle:0],nil];
					//id act = [CCSequence actions:[CCWavesTiles3D actionWithWaves:1 amplitude:0.2f grid:ccg(100, 100) duration:3.0f],nil];
					[spsFirst->sp runAction:[CCRepeatForever actionWithAction:act]];
					return;
				}
				spsSecond = sps;
				//如果当前选择是否与已选择精灵相同，或者当前选择与已选择精灵类型不同，取消选择
				if ((spsSecond == spsFirst) || (spsFirst->stype != spsSecond->stype)){
					[spsFirst->sp stopAllActions];
					//id act = [CCFadeIn actionWithDuration:0.01f];
					//[spsFirst->sp runAction:act];
					spsFirst->sp.rotation = 0;
					[spsFirst->sp runAction:[CCShow action]];
					//[spsFirst->sp transform];
#ifdef EN_SOUND	
					[[SimpleAudioEngine  sharedEngine] playEffect:@"wrongMusic.mp3"];
#endif
					//设置新选择项
					spsFirst = spsSecond;
					isSelect = YES;
					id act = [CCSequence actions:[CCRotateTo actionWithDuration:0.06f angle:10],
							  [CCRotateTo actionWithDuration:0.06f angle:0],
							  [CCRotateTo actionWithDuration:0.06f angle:-10],
							  [CCRotateTo actionWithDuration:0.06f angle:0],nil];
					[spsFirst->sp runAction:[CCRepeatForever actionWithAction:act]];
					isSelect = YES;
					return;
				}
				//当前选项与已选择项不同，且精灵类别相同
				if ((spsSecond != spsFirst) && (spsSecond->stype == spsFirst->stype)) {
					//路径判断，是否可以连接
					for (int i=0; i<5; i++) {
						spPathArray[i].x = 0;
						spPathArray[i].y = 0;
					}
					if([self checkLink :spsFirst->pos :spsSecond->pos])
					{
						
						//可以连接，画线
						//如果上一条线还没有清除，强制清除后再画
						while (isLined) {
							[self erasePath];
						}
						[self drawPath];
						isLined = YES;
						[self schedule:@selector(erasePath) interval:0.32f];
						
						//
						if (PAIR_BONUS > nLevel) {
							gameTime += (PAIR_BONUS - nLevel);
						}
						else {
							gameTime ++;
						}

						if (gameTime > levelTime) {
							gameTime = levelTime;
						}
						[prog stopAllActions];
						[prog runAction:[CCProgressFromTo actionWithDuration:(ccTime)gameTime from:(100*gameTime)/levelTime to:0]];

#ifdef EN_SOUND	
						[[SimpleAudioEngine  sharedEngine] playEffect:@"glass.wav"];
#endif
						//消除
						isSelect = NO;
						[spsFirst->sp stopAllActions];
						[spsFirst->sp runAction:[CCFadeOut actionWithDuration: 1.1f]];
						[spsSecond->sp runAction:[CCFadeOut actionWithDuration: 1.1f]];
						spsFirst->isLife = NO;
						spsSecond->isLife = NO;
						spsFirst = nil;
						spsSecond = nil;
						
						//加分，更新分数显示
						nScore += nScorePerPair;
						NSString *string = [NSString stringWithFormat:@"%06d", (int)nScore];
						
						CCBitmapFontAtlas *label1 = (CCBitmapFontAtlas*) [self getChildByTag:TAG_SCORE];
						[label1 setString:string];
						
						
						nSpCounts -= 2;
						if (nSpCounts <= 0) {
							//胜利
							isGameSuccessed = YES;
							[self unschedule:@selector(secondTimer:)];
							[prog stopAllActions];
							self.isTouchEnabled = NO;		
							[mniRefresh setIsEnabled:NO];
							[mniHint setIsEnabled:NO];
							[mniPause setIsEnabled:NO];
							
							
							CCLabel *label = [CCLabel labelWithString:@"Congratulations!" fontName:@"Marker Felt" fontSize:48];
							label.position = ccp(160,320);
							label.color = ccc3(250,50,50);
							nScore += gameTime*2;
							NSString *str = [NSString stringWithFormat:@"Finale Score:%06d", (int)nScore];
							CCLabel *lbScore = [CCLabel labelWithString:str fontName:@"Marker Felt" fontSize:32];
							lbScore.position = ccp(160,260);
							lbScore.color = ccc3(250,50,50);
							
							NSString *string = [NSString stringWithFormat:@"%06d", (int)nScore];
							
							CCBitmapFontAtlas *label1 = (CCBitmapFontAtlas*) [self getChildByTag:TAG_SCORE];
							[label1 setString:string];
							
							CCMenuItem * mni1 = [CCMenuItemFont itemFromString:@"next level" target:self selector:@selector(continueGmae:)];
							CCMenu *mn = [CCMenu menuWithItems:mni1, nil];
							mn.color = ccc3(80,200,250);
							mn.position = ccp( 160 , 180 );
							
							[self addChild:label z:100 tag:TAG_LBFINAL];
							[self addChild:lbScore z:100 tag:TAG_LBFINALSCORE];
							[self addChild:mn z:101 tag:TAG_MNCONTINUE];
						}
						else {
							//检查重排
							isAutoCheck = YES;
							[self checkAndDisplayHint:self];
							isAutoCheck = NO;
						}

					}
					else {//不可链接，取消选择
						isSelect = NO;
						[spsFirst->sp stopAllActions];
						spsFirst->sp.rotation = 0;
						[spsFirst->sp runAction:[CCShow action]];
						spsFirst = nil;
#ifdef EN_SOUND	
						[[SimpleAudioEngine  sharedEngine] playEffect:@"wrongMusic.mp3"];
#endif
						//设置新选择项
						spsFirst = spsSecond;
						isSelect = YES;
						id act = [CCSequence actions:[CCRotateTo actionWithDuration:0.06f angle:10],
								  [CCRotateTo actionWithDuration:0.06f angle:0],
								  [CCRotateTo actionWithDuration:0.06f angle:-10],
								  [CCRotateTo actionWithDuration:0.06f angle:0],nil];
						[spsFirst->sp runAction:[CCRepeatForever actionWithAction:act]];
						isSelect = YES;
						return;
						
					}
				}
				
			}
		}
	}
	
	return;
}

- (BOOL) checkLink :(CGPoint) firstSp : (CGPoint) secondSp
{
	spPathArray[0] = secondSp;
	wayPointCnt = 1;

		if ([self checkOneLine:firstSp :secondSp]) {
		return YES;
	}
	if ([self checkTwoLine:firstSp :secondSp]) {
		return YES;
	}
	if ([self checkThreeLine:firstSp :secondSp]) {
		return YES;
	}
	return NO;
}

- (BOOL) checkOneLine :(CGPoint) firstSp : (CGPoint) secondSp
{
	int x0,x1,y0,y1,x00,y00;
	BOOL xDirect;
	if (firstSp.y == secondSp.y) {
		xDirect = YES;
	}
	else if(firstSp.x == secondSp.x){
		xDirect = NO;
	}
	else {
		return NO;
	}

	SpriteStatus * sps;
	if (xDirect) {
		if ((firstSp.x - secondSp.x) > 0) {
			x1 = firstSp.x;
			x0 = secondSp.x;
			x00 = secondSp.x;
		}
		else {
			x0 = firstSp.x;
			x1 = secondSp.x;
			x00 = firstSp.x;
		}
		y0 = firstSp.y;
		do {
			x0 +=1;
			if (x0 == x1) {
				spPathArray[wayPointCnt] = ccp(firstSp.x,firstSp.y);
				wayPointCnt++;
				return YES;
			}
			sps = mapArray[x0][y0];
			if (sps->isLife) {
				return NO;
			}
		}while(1);
	}
	else
	{
		if((firstSp.y - secondSp.y) > 0){
			y1 = firstSp.y;
			y0 = secondSp.y;
			y00 = secondSp.y;
		}
		else {
			y0 = firstSp.y;
			y1 = secondSp.y;
			y00 = firstSp.y;
		}
		x0 = firstSp.x;
		do {
			y0 +=1;
			sps = mapArray[x0][y0];
			if (y0 == y1) {
				spPathArray[wayPointCnt] = ccp(firstSp.x,firstSp.y);
				wayPointCnt++;
				
				return YES;
			}
			if (sps->isLife) {
				return NO;
			}
		}while(1);
	}
	return NO;
}

- (BOOL) checkTwoLine :(CGPoint) firtSp : (CGPoint) secondSp
{
	//往一个方向走，不能走则换方向，每一步调用checkOneLine，成功则返回，
	//失败继续走，直到不能前进。
	//测试：注释。。。
	
	SpriteStatus *sps;
	int xt,yt;
	xt = firtSp.x;
	yt = firtSp.y;
	//firstSp往左（x－1）
	do {
		xt -= 1;
		if (xt < 0) {
			break;
		}
		sps = mapArray[xt][yt];
		if(sps->isLife)
			break;
		if ([self checkOneLine :ccp(xt,yt) :secondSp]) {
			spPathArray[wayPointCnt] = firtSp;
			wayPointCnt++;
			return YES;
		}
	} while (1);

	xt = firtSp.x;
	yt = firtSp.y;
	//firstSp往右（x＋1）
	do {
		xt += 1;
		if (xt > MAX_SPRITE_COL+1) {
			break;
		}
		sps = mapArray[xt][yt];
		if(sps->isLife)
			break;
		if ([self checkOneLine :ccp(xt,yt) :secondSp]) {
			spPathArray[wayPointCnt] = firtSp;
			wayPointCnt++;
			return YES;
		}
	} while (1);
	
	xt = firtSp.x;
	yt = firtSp.y;
	//firstSp往上（y－1）
	do {
		yt -= 1;
		if (yt < 0) {
			break;
		}
		sps = mapArray[xt][yt];
		if(sps->isLife)
			break;
		if ([self checkOneLine :ccp(xt,yt) :secondSp]) {
			spPathArray[wayPointCnt] = firtSp;
			wayPointCnt++;
			return YES;
		}
	} while (1);
	
	xt = firtSp.x;
	yt = firtSp.y;
	//firstSp往下（y＋1）
	do {
		yt += 1;
		if (yt > MAX_SPRITE_ROW+1) {
			break;
		}
		sps = mapArray[xt][yt];
		if(sps->isLife)
			break;
		if ([self checkOneLine :ccp(xt,yt) :secondSp]) {
			spPathArray[wayPointCnt] = firtSp;
			wayPointCnt++;
			return YES;
		}
	} while (1);
	
	return NO;
}

- (BOOL) checkThreeLine :(CGPoint) firtSp : (CGPoint) secondSp
{
	//往一个方向走，不能走则换方向，每一步调用checkOneLine，成功则返回，
	//失败继续走，直到不能前进。
	
	SpriteStatus *sps;
	int xt,yt;
	xt = firtSp.x;
	yt = firtSp.y;
	//firstSp往左（x－1）
	do {
		xt -= 1;
		if (xt < 0) {
			break;
		}
		sps = mapArray[xt][yt];
		if(sps->isLife)
			break;
		if ([self checkTwoLine :ccp(xt,yt) :secondSp]) {
			spPathArray[wayPointCnt] = firtSp;
			wayPointCnt++;
			return YES;
		}
	} while (1);
	
	xt = firtSp.x;
	yt = firtSp.y;
	//firstSp往右（x＋1）
	do {
		xt += 1;
		if (xt > MAX_SPRITE_COL+1) {
			break;
		}
		sps = mapArray[xt][yt];
		if(sps->isLife)
			break;
		if ([self checkTwoLine :ccp(xt,yt) :secondSp]) {
			spPathArray[wayPointCnt] = firtSp;
			wayPointCnt++;
			return YES;
		}
	} while (1);
	
	xt = firtSp.x;
	yt = firtSp.y;
	//firstSp往上（y－1）
	do {
		yt -= 1;
		if (yt < 0) {
			break;
		}
		sps = mapArray[xt][yt];
		if(sps->isLife)
			break;
		if ([self checkTwoLine :ccp(xt,yt) :secondSp]) {
			spPathArray[wayPointCnt] = firtSp;
			wayPointCnt++;
			return YES;
		}
	} while (1);
	
	xt = firtSp.x;
	yt = firtSp.y;
	//firstSp往下（y＋1）
	do {
		yt += 1;
		if (yt > MAX_SPRITE_ROW+1) {
			break;
		}
		sps = mapArray[xt][yt];
		if(sps->isLife)
			break;
		if ([self checkTwoLine :ccp(xt,yt) :secondSp]) {
			spPathArray[wayPointCnt] = firtSp;
			wayPointCnt++;
			return YES;
		}
	} while (1);
		
	return NO;
}

- (void) drawline : (CGPoint)From : (CGPoint)To
{
	int x0,x1,y0,y1;
	[rTexure begin];
	if (From.y == To.y) {
		if((From.x - To.x) > 0)
		{
			x0 = To.x; x1 = From.x; y0 = From.y;
		}
		else {
			x0 = From.x; x1 = To.x; y0 = From.y;
		}
		
		for (int j=SPRITE_WIDTH*(x1-x0); j>=0; j-=4) {
			[spBrush setPosition:ccp(MAP_LEFT+x0*SPRITE_WIDTH-SPRITE_WIDTH/2+j, 
									 MAP_UP-(y0*SPRITE_HEIGHT- SPRITE_HEIGHT/2))];
			[spBrush visit];
		}
	}
	else {
		if((From.y - To.y) > 0)
		{
			y0 = To.y; y1 = From.y; x0 = From.x;
		}
		else {
			y0 = From.y; y1 = To.y; x0 = From.x;
		}
		
		for (int j=SPRITE_HEIGHT*(y1-y0); j>0; j-=4) {
			[spBrush setPosition:ccp(MAP_LEFT+x0*SPRITE_WIDTH-SPRITE_WIDTH/2, 
									 MAP_UP-(y0*SPRITE_HEIGHT-SPRITE_HEIGHT/2+j))];
			[spBrush visit];
		}
	}
	
	[rTexure end];
}

- (void) drawPath
{
	// create a render texture, this is what we're going to draw into
	
	CGSize s = [[CCDirector sharedDirector] winSize];	
	rTexure = [[CCRenderTexture renderTextureWithWidth:s.width height:s.height] retain];
	[rTexure setPosition:ccp(s.width/2, s.height/2)];
	[self addChild:rTexure z:20 tag:TAG_SPBRUSH];
	spBrush = [[CCSprite spriteWithFile:@"Default.png" rect:CGRectMake(0, 475, 4, 4)] retain];
	for (int i=0; i<wayPointCnt-1; i++) {
		[self drawline:spPathArray[i]:spPathArray[i+1]];
	}
}

- (void) erasePath
{
	[self unschedule:@selector(erasePath)];
	[self removeChild:(CCNode *)rTexure cleanup:YES];
	[rTexure release];
	[spBrush release];
	isLined = NO;
	
}

- (void)continueGmae : (id)sender
{
	
	//	[self returnMain:sender];
	//清理不需要的内容
	// 重新整理一遍tag的编号，用宏定义，并且区分静态Tag和动态tag
	
	
	
	//重新初始化相关参数，增加难度
	isSelect = NO;
	isLined = NO;
	isGameOver = NO;
	isGameSuccessed = NO;
	nSpCounts = MAX_SPRITES;
	
	
	nScorePerPair += 5;
	nLevel ++;

	nLifeCounts += nLevel % 3 ? 0 : 1;
	nHints += nLevel % 3 ? 0 : 1;

	[mniPause setIsEnabled:YES];
	if(nLifeCounts > 0)
		[mniRefresh setIsEnabled:YES];
	if(nHints > 0)
		[mniHint setIsEnabled:YES];
	
	if(nLifeCounts > 9)
		nLifeCounts = 9;
	if(nHints > 9)
		nHints = 9;

	NSString *string1 = [NSString stringWithFormat:@"%d", (int)nLifeCounts];
	
	CCLabel *label1 = (CCLabel*)[self getChildByTag:TAG_REFRESH_CNT];
	[label1 setString:string1];
	
	NSString *string2 = [NSString stringWithFormat:@"%d", (int)nHints];
	
	CCLabel *label2 = (CCLabel*)[self getChildByTag:TAG_HINT_CNT];
	[label2 setString:string2];
	
	NSString *strLevel = [NSString stringWithFormat:@"Level %d", (int)nLevel];
	CCLabel *lbLevel = (CCLabel*)[self getChildByTag:TAG_LBLEVEL];
	[lbLevel setString:strLevel];

	
	gameTime = GAMETIME;
	
	int n = nLevel;
	while (n--) {
		gameTime -= GAMETIME / 10;
	}
	levelTime = gameTime;
	[prog runAction:[CCProgressFromTo actionWithDuration:(ccTime)gameTime from:(100*gameTime)/levelTime to:0]];
	
	
	for (int i=0; i<MAX_SPRITE_COL+2; i++) {
		for (int j=0; j<MAX_SPRITE_ROW+2; j++) {
			if (mapArray[i][j]->sp != nil) {
				[mgr removeChild:mapArray[i][j]->sp cleanup:YES];
				[mapArray[i][j] release];
			}
		}
	}
	[gSelf removeChild:mgr cleanup:YES];
	
	[gSelf removeChild:[gSelf getChildByTag:TAG_LBFINAL] cleanup:YES];
	[gSelf removeChild:[gSelf getChildByTag:TAG_LBFINALSCORE] cleanup:YES];
	[gSelf removeChild:[gSelf getChildByTag:TAG_MNCONTINUE] cleanup:YES];
	
	
	nCrtTypeOfSp += nLevel/2;
	if (nCrtTypeOfSp > MAXTYPE_OF_SPRITE) {
		nCrtTypeOfSp = MAXTYPE_OF_SPRITE;
	}
	
	int nTotal = MAX_SPRITES;
	memset(cntArray, 0, sizeof(int) * MAXTYPE_OF_SPRITE);
	while (nTotal) {
		for (int i=0; i<nCrtTypeOfSp; i++) {
			cntArray[i] += 2;
			nTotal -= 2;
			if (nTotal <= 0) {
				break;
			}
		}
		
	}
	
	[self initSpriteMap];
	//开始游戏
	
	
	self.isTouchEnabled = YES;		
	
	
	[self schedule:@selector(secondTimer:) interval:1];
	
	
}
- (void) OnSetSound:(id) sender
{
#ifdef EN_SOUND
	[SimpleAudioEngine sharedEngine].muted = [sender selectedIndex];//==0?YES:NO;
#endif	
}

- (void) pauseGame:(id)sender
{
	[self unschedule:@selector(secondTimer:)];
	[[CCDirector sharedDirector] pause];
	CCScene *sc = [CCScene node];
	[sc addChild:[PausePage node]];	
	[[CCDirector sharedDirector] pushScene:  [CCTurnOffTilesTransition transitionWithDuration:0.5f scene:sc]];	
	[[CCDirector sharedDirector] resume];
	[self schedule:@selector(secondTimer:) interval:1];
}

- (void) returnMain: (id) sender
{
#ifdef EN_SOUND	
	[[SimpleAudioEngine sharedEngine] stopBackgroundMusic];
#endif

	
	CCScene *sc = [CCScene node];
	[sc addChild:[mainpage node]];	
	[[CCDirector sharedDirector] replaceScene:  [CCTurnOffTilesTransition transitionWithDuration:0.5f scene:sc]];	
//	[[CCDirector sharedDirector] popScene];
}
// on "dealloc" you need to release all your retained objects
- (void) dealloc
{
	// in case you have something to dealloc, do it in this method
	// in this particular example nothing needs to be released.
	// cocos2d will automatically release all the children (Label)
	
	// don't forget to call "super dealloc"
	[super dealloc];
}

@end
